package com.khstudio.videocapture.view;

import java.util.LinkedList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;

import com.khstudio.api.util.KhBitmapFactory;

public class KhVideoSaveEffectView extends View {
    private static final int LAYOUT_UPDATE_NONE     = 0x0000;
    private static final int LAYOUT_UPDATE_DO       = 0x0001;

    private Context mContext;

    private int mWidth;
    private int mHeight;
    private int mChangeLayout;

    private Paint mPaint;

    private LinkedList<EffectData> mEffectData;

    private Rect mDstRect;
    private int mDstWidth;
    private int mDstHeight;

    private int mDuration;
    private KVideoEditSaveEffectListener mListener;

    public interface KVideoEditSaveEffectListener {
        void onEffectUpdate(String path, Bitmap bm);
    }

    private class EffectData {
        static final int EFFECT_MODE_SCALE = 0x0001;
        static final int EFFECT_MODE_TRANS = 0x0002;

        String path;

        Rect src;
        int  srcwidth;
        int  srcheight;

        Rect dst;
        int  dstwidth;
        int  dstheight;

        Bitmap bitmap;

        int scaleDuration;
        int transDuration;
        int mode;

        long time;
        boolean isEnd;

        EffectData(String path, Bitmap bitmap, Rect src, Rect dst, int scaleDur, int transDur) {
            this.path = path;

            this.src = src;
            srcwidth = src.right - src.left;
            srcheight = src.bottom - src.top;

            this.dst = dst;
            dstwidth = dst.right - dst.left;
            dstheight = dst.bottom - dst.top;

            if(scaleDur == 0) {
                mode = EFFECT_MODE_TRANS;
            } else {
                mode = EFFECT_MODE_SCALE;
                scaleDuration = scaleDur;
            }
            transDuration = transDur;

            time = System.currentTimeMillis();
            isEnd = false;

            this.bitmap = bitmap;
        }

        public Rect getCurRect(long tm) {
            long dur = tm - time;
//            log.e("KVideoEditSaveEffect : tm %d time %d", tm, time);
            if(mode == EFFECT_MODE_SCALE) {
                if(dur > scaleDuration) {
                    mode = EFFECT_MODE_TRANS;

                    int l = src.left + srcwidth / 4;
                    int r = l + srcwidth / 2;
                    int t = src.top + srcheight / 4;
                    int b = t + srcheight / 2;

                    src = new Rect(l, t, r, b);
                    srcwidth = src.right - src.left;
                    srcheight = src.bottom - src.top;
                    time = System.currentTimeMillis();

                    return src;
                }

                int width = (int)  (srcwidth  - srcwidth/2  * (double)dur / (double)scaleDuration);
                int height = (int) (srcheight - srcheight/2 * (double)dur / (double)scaleDuration);

                int l = src.left + (srcwidth - width) / 2;
                int r = l + width;
                int t = src.top + (srcheight - height) / 2;
                int b = t + height;

                return new Rect(l, t, r, b);
            } else {
                if(dur > transDuration) {
                    isEnd = true;
                    return dst;
                }

                int width = (int)  (dstwidth  + (srcwidth  - dstwidth ) * (double)(transDuration - dur) / (double)transDuration);
                int height = (int) (dstheight + (srcheight - dstheight) * (double)(transDuration - dur) / (double)transDuration);

//                log.e("KVideoEditSaveEffect : getCurRect %d", dur);
                int l = (int) (src.left + (double)(dst.left - src.left) * (double)dur / (double)transDuration);
                int r = l + width;
                int t = (int) (src.top + (double)(dst.top - src.top) * (double)dur / (double)transDuration);
                int b = t + height;
//                log.e("KVideoEditSaveEffect : getCurRect l = %d r = %d t = %d b = %d ", l, r, t, b);
                return new Rect(l, t, r, b);
            }
        }
    }

    public KhVideoSaveEffectView(Context context) {
        this(context, null);
    }

    public KhVideoSaveEffectView(Context context, AttributeSet attrs) {
        this(context, attrs , 0);
    }

    public KhVideoSaveEffectView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        mContext = context;
        mListener = null;
        mChangeLayout = LAYOUT_UPDATE_NONE;

        mPaint = new Paint();

        mEffectData = new LinkedList<EffectData>();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if(changed) {
            mWidth = r - l;
            mHeight = b - t;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if(!mEffectData.isEmpty()) {

//            EffectData e = mEffectData.getFirst();
            EffectData removeData = null;

            for(EffectData e : mEffectData) {
                long tm = System.currentTimeMillis();

                canvas.save();
                canvas.translate(0 , 0);
                canvas.drawBitmap(e.bitmap, null, e.getCurRect(tm), mPaint);
                if(e.isEnd && removeData == null) removeData = e;
                canvas.restore();
            }

            if(removeData != null) {
                if(mListener != null) mListener.onEffectUpdate(removeData.path, removeData.bitmap);
                removeData.bitmap.recycle();
                mEffectData.remove(removeData);
            }
            invalidate();
        }
    }

    public void setSaveEffectListener(KVideoEditSaveEffectListener l) {
        mListener = l;
    }

    public void startSaveEffect(Rect dst, int duration) {
        mDstRect = new Rect(dst);
        mDstWidth = mDstRect.right - mDstRect.left;
        mDstHeight = mDstRect.bottom - mDstRect.top;
        mDuration = duration;
    }

    public void setSaveEffectImage(String path, Bitmap bm) {
        Bitmap tmp = KhBitmapFactory.createBitmapOnRatio(bm, mWidth, mHeight);

        int l = (mWidth - tmp.getWidth()) / 2;
        int r = l + tmp.getWidth();
        int t = (mHeight - tmp.getHeight()) / 2;
        int b = t + tmp.getHeight();

        int dstl = mDstRect.left + (mDstRect.right - mDstRect.left - mDstWidth) / 2;
        int dstr = dstl + mDstWidth;
        int dstt = mDstRect.top + (mDstRect.bottom - mDstRect.top - mDstHeight) / 2;
        int dstb = dstt + mDstHeight;

        EffectData e = new EffectData(path, tmp,
                                      new Rect(l, t, r, b),
                                      new Rect(dstl , dstt , dstr, dstb),
                                      200, 300);
        mEffectData.add(e);
        invalidate();
    }
}
